home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / tcp / Amster-source.lha / Amster_Install / Source / napster.c < prev    next >
C/C++ Source or Header  |  2001-03-27  |  20KB  |  955 lines

  1. /*
  2. ** Amster - Napster Protocol
  3. ** Copyright © 1999-2000 by Gürer Özen
  4. ** Copyright © 2000-2001 by Jacob Laursen
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. **
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with this program; if not, write to the Free Software
  18. ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. #include "amster.h"
  22.  
  23. #include "network.h"
  24.  
  25. #include "amster_Cat.h"
  26.  
  27. #define NAP_SWAPIP(x) ( ((x&0xFF)<<24) | ((x&0xFF00)<<8) | ((x&0xFF0000)>>8) | (x>>24) )
  28.  
  29. struct Library *SocketBase=NULL;
  30. u_long nap_sigmask;
  31. long nap_sock= -1;
  32. long loc_sock= -1;
  33.  
  34. char nap_host[512];
  35. char nap_server[512+6];
  36. unsigned short nap_port;
  37.  
  38. int nap_state= -1;
  39. #define NAPS_OFF -1
  40. #define NAPS_MAINCON 0
  41. #define NAPS_MAINON 1
  42. #define NAPS_CON 2
  43. #define NAPS_LOGIN 3
  44. #define NAPS_ON 4
  45.  
  46.  
  47. char nap_buffer[AMSTER_NAPBUFSIZE];
  48. char *nap_buf = &nap_buffer[4];
  49.  
  50. char *nap_linktype[] = {
  51.     (char*)_MSG_LINE_UNKNOWN,
  52.     (char*)_MSG_LINE_14400,
  53.     (char*)_MSG_LINE_28800,
  54.     (char*)_MSG_LINE_33600,
  55.     (char*)_MSG_LINE_57600,
  56.     (char*)_MSG_LINE_64000,
  57.     (char*)_MSG_LINE_128000,
  58.     (char*)_MSG_LINE_CABLE,
  59.     (char*)_MSG_LINE_DSL,
  60.     (char*)_MSG_LINE_T1,
  61.     (char*)_MSG_LINE_T3,
  62.     NULL
  63. };
  64.  
  65. BOOL nap_logininit(void);
  66. int nap_connect(char *server, unsigned short port);
  67. void NapsterLogin(void);
  68. int nap_recv(u_char *buf);
  69. void nap_interpret(u_int com, char *data);
  70. void nap_parseresult(int type, char *data);
  71. char *nap_token(char **s);
  72. u_long nap_ltoken(char **str);
  73. int nap_itoken(char **str);
  74. char *getneterror(int type);
  75. void ExitListenerThread(listener l, int ret);
  76.  
  77.  
  78. void nap_login_fromlist(char *server, unsigned short port)
  79. {
  80.     if (!nap_logininit()) return;
  81.  
  82.     nap_state = NAPS_CON;
  83.     gui_stat((char*)MSG_STATUS2_CONNECTINGTO_TMP, server, port);
  84.     if (!nap_connect(server, port)) {
  85.         nap_logout();
  86.         return;
  87.     }
  88. }
  89.  
  90.  
  91. void nap_login(void)
  92. {
  93.     if (!nap_logininit()) return;
  94.  
  95.     if (prf->LeafServer) {
  96.         nap_state = NAPS_CON;
  97.         gui_stat((char*)MSG_STATUS2_CONNECTINGTO_TMP, prf->LeafServer, prf->LeafPort);
  98.         if (!nap_connect(prf->LeafServer, prf->LeafPort)) {
  99.             nap_logout();
  100.             return;
  101.         }
  102.     }
  103.     else {
  104.         nap_state = NAPS_MAINCON;
  105.         gui_stat((char*)MSG_STATUS2_FINDINGOPTIMAL);
  106.         if (!nap_connect(prf->MetaServer, prf->MetaPort)) {
  107.             nap_logout();
  108.             return;
  109.         }
  110.     }
  111. }
  112.  
  113.  
  114. BOOL nap_logininit(void)
  115. {
  116.     gui_state(CONNECTING);
  117.     SocketBase = OpenLibrary("bsdsocket.library", 0);
  118.     if (!SocketBase) {
  119.         gui_stat((char *)MSG_NO_TCPIP);
  120.         nap_logout();
  121.         return FALSE;
  122.     }
  123.     SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK), (char *)nap_sigmask, TAG_DONE);
  124.  
  125.     return TRUE;
  126. }
  127.  
  128.  
  129. void nap_logout(void)
  130. {
  131.     nap_state = NAPS_OFF;
  132.     if (nap_sock>=0) CloseSocket(nap_sock);
  133.     nap_sock = -1;
  134.     if (loc_sock>=0) CloseSocket(loc_sock);
  135.     loc_sock = -1;
  136.     if (SocketBase) CloseLibrary(SocketBase);
  137.     SocketBase = NULL;
  138.     gui_state(DISCONNECTED);
  139. }
  140.  
  141.  
  142. void nap_listen(void)
  143. {
  144.     static u_char buf[AMSTER_NAPBUFSIZE];
  145.     static struct fd_set fds;
  146.     static struct timeval tv;
  147.  
  148.     if (nap_state == NAPS_OFF) return;
  149.  
  150.     FD_ZERO(&fds);
  151.     FD_SET(nap_sock,&fds);
  152.     tv.tv_sec = 0;
  153.     tv.tv_usec = 0;
  154.  
  155.     switch (nap_state) {
  156.         case NAPS_MAINCON:
  157.             if (WaitSelect(nap_sock+1,NULL,&fds,NULL,&tv,0) != 1) break;
  158.             {
  159.                 long tmp=0;
  160.                 IoctlSocket(nap_sock,FIONBIO,(char*)&tmp);
  161.                 nap_state = NAPS_MAINON;
  162.             }
  163.  
  164.         case NAPS_MAINON:
  165.             if (WaitSelect(nap_sock+1,&fds,NULL,NULL,&tv,0) != 1) break;
  166.             {
  167.                 int r;
  168.                 char *addr, *col;
  169.                 int port = 0;
  170.  
  171.                 r = recv(nap_sock, buf, 255,0);
  172.                 CloseSocket(nap_sock);
  173.                 nap_sock = -1;
  174.                 if (r <= 0) {
  175.                     gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_server, getneterror(Errno()));
  176.                     nap_logout();
  177.                     return;
  178.                 }
  179.                 buf[r] = 0;
  180.                 col = strchr(buf, '\n');
  181.                 if (col) *col=0;
  182.                 if (strncmp(buf,"wait",4)==0 || strncmp(buf,"busy",4)==0 || strncmp(buf,"127.0.0.1",9)==0) {
  183.                     /* 127.0.0.1:1111 = The load balancer has rejected our connection to the
  184.                        service (generally because the load/rate is too high) */
  185.                     gui_stat((char *)MSG_INFO_SERVERBUSY);
  186.                     nap_logout();
  187.                     return;
  188.                 }
  189.                 gui_debugf((char *)MSG_INFO_OPTIMAL, buf);
  190.  
  191.                 addr = strdup(buf);
  192.                 col = strtok(addr, ":");
  193.                 if (col) col = strtok(NULL, "");
  194.                 if (col) port = atoi(col);
  195.  
  196.                 gui_stat((char *)MSG_STATUS2_CONNECTINGTO_TMP, addr, port);
  197.                 if (!nap_connect(addr, port)) {
  198.                     nap_logout();
  199.                     free(addr);
  200.                     return;
  201.                 }
  202.                 free(addr);
  203.                 nap_state = NAPS_CON;
  204.             }
  205.             break;
  206.  
  207.         case NAPS_CON:
  208. #ifdef AMSTER_DEBUG
  209. gui_debug("NAPS_CON");
  210. #endif
  211.             if (WaitSelect(nap_sock+1,NULL,&fds,NULL,&tv,0) != 1) break;
  212.             {
  213.                 long tmp=0;
  214.                 int r;
  215.  
  216.                 IoctlSocket(nap_sock, FIONBIO, (char *)&tmp);
  217.  
  218.                 gui_stat((char *)MSG_STATUS2_LOGGINGINTO_TMP, nap_server, nap_port);
  219.                 gui_state(LOGGING_IN);
  220.  
  221.                 if (prf->regflag == 2 || (prf->regflag == 1 && prf->BypassRegistration == FALSE)) {
  222.                     r = nap_sendbuf(NAPC_CHECK_NAME, prf->user);
  223.  
  224.                     /* Create user before we attempt to log in */
  225.  
  226.                     if (r == -1) {
  227.                         prf->regflag = 1;
  228.                         if (Errno() == EPIPE) {
  229. #ifdef AMSTER_DEBUG
  230.                             gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP2, nap_server, nap_port, getneterror(Errno()));
  231. #else
  232.                             gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP2, nap_server, 0, getneterror(Errno()));
  233. #endif
  234.                             nap_logout();
  235.                             return;
  236.                         }
  237.                     }
  238.  
  239.                 }
  240.                 else NapsterLogin();
  241.  
  242.                 nap_state = NAPS_ON;
  243.  
  244.             }
  245.             break;
  246.  
  247.         case NAPS_ON:
  248.             while (1) {
  249.                 int r;
  250.                 FD_ZERO(&fds);
  251.                 FD_SET(nap_sock,&fds);
  252.                 tv.tv_sec=0;
  253.                 tv.tv_usec=0;
  254.                 if (WaitSelect(nap_sock+1, &fds, NULL, NULL, &tv, 0) < 1) {
  255.                     return;
  256.                 }
  257.  
  258.                 r = nap_recv(buf);
  259.                 if (r == -1) {
  260.                     gui_stat((char *)MSG_ERR_NETWORKERROR);
  261.                     nap_logout();
  262.                     return;
  263.                 }
  264.                 if (r == 1) nap_interpret(buf[2]+(buf[3]<<8), buf+4);
  265.             }
  266.     }
  267. }
  268.  
  269.  
  270. void NapsterLogin(void)
  271. {
  272. #ifdef AMSTER_DEBUG
  273. gui_debug("NAPS_LOGIN");
  274. #endif
  275.     if (prf->regflag == 1) {
  276. #ifdef AMSTER_DEBUG
  277.         sprintf(nap_buf, "%s %s %d \"%s\" %d", prf->user, prf->pass, prf->port, prf->napvers, prf->link);
  278. #else
  279.         sprintf(nap_buf, "%s %s %d \"%s\" %d", prf->user, prf->pass, 0, prf->napvers, prf->link);
  280. #endif
  281.     }
  282.     else {
  283. #ifdef AMSTER_DEBUG
  284.         sprintf(nap_buf, "%s %s %d \"%s\" %d", gui->ConnectUser, gui->ConnectPw, prf->port, prf->napvers, prf->link);
  285. #else
  286.         sprintf(nap_buf, "%s %s %d \"%s\" %d", gui->ConnectUser, gui->ConnectPw, 0, prf->napvers, prf->link);
  287. #endif
  288.     }
  289.     prf->regflag = 1;
  290.     nap_send(NAPC_LOGIN_REQUEST);
  291. }
  292.  
  293.  
  294. void nap_send(u_int com)
  295. {
  296.     int len;
  297.  
  298.     if (gui_onlinestate < CONNECTING) return;
  299.     /* Avoid crash - but calling functions should check this first! */
  300.  
  301.     len = strlen(nap_buf);
  302.     nap_buffer[0] = len&0xFF;
  303.     nap_buffer[1] = (len&0xFF00)>>8;
  304.     nap_buffer[2] = com&0xFF;
  305.     nap_buffer[3] = (com&0xFF00)>>8;
  306.     send(nap_sock,nap_buffer,4+len,0);
  307. }
  308.  
  309.  
  310. int nap_sendbuf(u_int com, char *buf)
  311. {
  312.     static u_char hdr[4];
  313.     int len, r;
  314.  
  315.     if (gui_onlinestate < CONNECTING) return -1;
  316.     /* Avoid crash - but calling functions should check this first! */
  317.  
  318.     len = strlen(buf);
  319.     hdr[0] = len&0xFF;
  320.     hdr[1] = (len&0xFF00)>>8;
  321.     hdr[2] = com&0xFF;
  322.     hdr[3] = (com&0xFF00)>>8;
  323.  
  324.     r = send(nap_sock, hdr, 4, 0);
  325.     if (r <= 0) return r;
  326.  
  327.     r = send(nap_sock, buf, len, 0);
  328.     if (r <= 0) return r;
  329.     else return 0;
  330. }
  331.  
  332.  
  333. void nap_songfree(song s)
  334. {
  335.     if (!s) return;
  336.     if (s->title) free(s->title);
  337.     if (s->md5) free(s->md5);
  338.     if (s->user) free(s->user);
  339.     free(s);
  340. }
  341.  
  342.  
  343. song nap_songdup(song s)
  344. {
  345.     song sn;
  346.  
  347.     sn = malloc(sizeof(_song));
  348.     if (!sn) return(NULL);
  349.     memset(sn,0,sizeof(_song));
  350.  
  351.     sn->title = strdup(s->title);
  352.     sn->md5 = strdup(s->md5);
  353.     sn->size = s->size;
  354.     sn->bit = s->bit;
  355.     sn->freq = s->freq;
  356.     sn->time = s->time;
  357.     sn->user = strdup(s->user);
  358.     sn->ip = s->ip;
  359.     sn->link = s->link;
  360.  
  361.     if (!sn->title || !sn->md5 || !sn->user) {
  362.         nap_songfree(sn);
  363.         return(NULL);
  364.     }
  365.  
  366.     return(sn);
  367. }
  368.  
  369.  
  370. char *nap_strippath(char *name)
  371. {
  372.     int i;
  373.     char tmp;
  374.  
  375.     for (i=strlen(name)-1; i>=0; i--) {
  376.         tmp = name[i];
  377.         if (tmp==':' || tmp=='/' || tmp=='\\') return(name+i+1);
  378.     }
  379.     return(name);
  380. }
  381.  
  382.  
  383. /* private functions */
  384.  
  385. int nap_connect(char *server, unsigned short port)
  386. {
  387.     struct hostent *host;
  388.     struct sockaddr_in sin;
  389.     long tmp=1;
  390.  
  391.     if (!port) {
  392.         gui_stat((char *)MSG_INFO_PORTNEEDED);
  393.         return(0);
  394.     }
  395.  
  396.     host = gethostbyname(server);
  397.     if (!host) {
  398.         gui_stat((char *)MSG_ERR_LOOKUPFAILED);
  399.         return(0);
  400.     }
  401.     memcpy(&sin.sin_addr, host->h_addr, host->h_length);
  402.     sin.sin_family = host->h_addrtype;
  403.     sin.sin_port = port;
  404.     sin.sin_len = sizeof(sin);
  405.  
  406.     strcpy(nap_host, host->h_name);
  407.     strcpy(nap_server, server);
  408.     nap_port = port;
  409.  
  410.     nap_sock = socket(AF_INET,SOCK_STREAM,0);
  411.     if (nap_sock < 0) {
  412.         gui_debug((char *)MSG_ERR_SOCKETERROR);
  413.         return(0);
  414.     }
  415.  
  416.     IoctlSocket(nap_sock, FIOASYNC, (char *)&tmp);
  417.     IoctlSocket(nap_sock, FIONBIO,  (char *)&tmp);
  418.  
  419.     tmp = connect(nap_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
  420.     if (tmp != -1) return(1);
  421.     if (Errno() == EINPROGRESS) return(1);
  422.  
  423.     gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_host, getneterror(Errno()));
  424.     return(0);
  425. }
  426.  
  427.  
  428. int nap_recv(u_char *buf)
  429. {
  430.     static u_int blen=0;
  431.     u_int len=4;
  432.     int ret;
  433.  
  434.     if (blen>=4) {
  435.         len = buf[0] + (buf[1]<<8) + 4;
  436.         if (len==0) {
  437.             buf[blen] = 0;
  438.             blen = 0;
  439.             return(1);
  440.         }
  441.     }
  442.  
  443.  
  444.     ret = recv(nap_sock, buf+blen, len-blen, 0);
  445.     if (ret <= 0) {
  446.         blen = 0;
  447.         return(-1);
  448.     }
  449.     blen += ret;
  450.  
  451.  
  452.     if (blen == 4) {
  453.         len = buf[0] + (buf[1]<<8) + 4;
  454.         if (len == 0) {
  455.             buf[blen] = 0;
  456.             blen = 0;
  457.             return(1);
  458.         }
  459.     }
  460.  
  461.     if (blen == len) {
  462.         buf[blen] = 0;
  463.         blen = 0;
  464.         return(1);
  465.     }
  466.  
  467.     return(0);
  468. }
  469.  
  470.  
  471. void nap_interpret(u_int com, char *data)
  472. {
  473.     switch (com) {
  474.         case NAPC_PUBLICMSGRECV:
  475.         case NAPC_JOINACK:
  476.         case NAPC_JOINMSG:
  477.         case NAPC_USERPART:
  478.         case NAPC_USERLIST:
  479.         case NAPC_USERLISTEND:
  480.         case NAPC_CHANNELTOPIC:
  481.             chat_interpret(com, data);
  482.             break;
  483.         case NAPC_CHANNELPART:
  484.             gui_debugf("Left channel %s.", data);
  485.             break;
  486.         case NAPC_CHANNEL_ENTRY:
  487.             {
  488.             char *channel;
  489.             int users;
  490.  
  491.             channel = nap_token(&data);
  492.             users = nap_itoken(&data);
  493.             DoMethod(gui->WI_ChannelList, CHANLIST_ENTRY, channel, users, data);
  494.             break;
  495.             }
  496.         case NAPC_LIST_CHANNELS:
  497.             /* End of channel list */
  498.             break;
  499.         case NAPC_USER_SIGNON:
  500.         case NAPC_USER_SIGNOFF:
  501.         case NAPC_HOTLIST_ACK:
  502.         case NAPC_HOTLIST_ERROR:
  503.             HotlistInterpret(com, data);
  504.             break;
  505.         case NAPC_LOGINERROR:
  506.             gui_debugf((char *)MSG_INFO_LOGINERROR, data);
  507.             if (strcmp(data, "Invalid Password") == 0)
  508.                 MUI_Request(gui->app, gui->win, 0L,
  509.                     (char *)MSG_LOGINERROR_TITLE,
  510.                     (char *)MSG_OK_GAD,
  511.                     (char *)MSG_LOGINERROR_WRONGPW);
  512.             break;
  513.         case NAPC_REGSUCCESS:
  514.             gui_debug((char *)MSG_INFO_REGSUCCESS);
  515.             if (prf->regflag == 1) {
  516. #ifdef AMSTER_DEBUG
  517.                 sprintf(nap_buf, "%s %s %d \"%s\" %d %s", prf->user, prf->pass, prf->port, prf->napvers, prf->link, prf->email);
  518. #else
  519.                 sprintf(nap_buf, "%s %s %d \"%s\" %d %s", prf->user, prf->pass, 0, prf->napvers, prf->link, prf->email);
  520. #endif
  521.             }
  522.             else {
  523. #ifdef AMSTER_DEBUG
  524.                 sprintf(nap_buf, "%s %s %d \"%s\" %d %s", gui->ConnectUser, gui->ConnectPw, prf->port, prf->napvers, prf->link, prf->email);
  525. #else
  526.                 sprintf(nap_buf, "%s %s %d \"%s\" %d %s", gui->ConnectUser, gui->ConnectPw, 0, prf->napvers, prf->link, prf->email);
  527. #endif
  528.             }
  529.             nap_send(NAPC_NEW_USER);
  530.             NapsterLogin();
  531.             break;
  532.         case NAPC_REGUSED:
  533.             gui_debug((char *)MSG_INFO_REGUSED);
  534.             NapsterLogin();
  535.             break;
  536.         case NAPC_NICKINVALID:
  537.             MUI_Request(gui->app, gui->win, 0L,
  538.                 (char *)MSG_LOGINERROR_TITLE,
  539.                 (char *)MSG_OK_GAD,
  540.                 (char *)MSG_LOGINERROR_INVALIDNAME);
  541.             break;
  542.         case NAPC_SEARCHRESULT:
  543.             nap_parseresult(0, data);
  544.             break;
  545.         case NAPC_SEARCHCOMPLETE:
  546.             gui_found(NULL, 0);
  547.             break;
  548.         case NAPC_BROWSERESULT:
  549.             nap_parseresult(1, data);
  550.             break;
  551.         case NAPC_BROWSECOMPLETE:
  552.             gui_found(NULL, 1);
  553.             break;
  554.         case NAPC_FILECOUNT:
  555.             {
  556.             int a,b,c;
  557.             a = nap_itoken(&data);
  558.             b = nap_itoken(&data);
  559.             c = nap_itoken(&data);
  560.             gui_srvstat(a,b,c);
  561.             break;
  562.             }
  563.         case NAPC_PRIVATEMSG:
  564.             {
  565.             char *nick;
  566.  
  567.             nick = nap_token(&data);
  568.             DoMethod(gui->mwin, MSG_GOT, nick, data);
  569.             break;
  570.             }
  571.         case NAPC_FILEINFO:
  572.             {
  573.             char *title, *user;
  574.             u_long ip;
  575.             int port;
  576.  
  577.             user = nap_token(&data);
  578.             ip = nap_ltoken(&data);
  579.             port = nap_itoken(&data);
  580.             title = nap_token(&data);
  581.  
  582.             DoMethod(gui->dwin, DL_START, title, user, NAP_SWAPIP(ip), port);
  583.             }
  584.             break;
  585.         case NAPC_LOGINRESP:
  586.             DoMethod(gui->WI_Navigator, NAVI_MARKSERVER, nap_server, nap_port);
  587.             DoMethod(gui->WI_Hotlist, HOTLIST_UPLOAD);
  588.             DoMethod(gui->shwin, SHARE_NOTIFYALL);
  589.             gui_state(ONLINE);
  590.             break;
  591.         case NAPC_WHOISRESP:
  592.             msg_gotwhois(data);
  593.             break;
  594.         case NAPC_WHOWASRESP:
  595.             {
  596.             char *user, *level;
  597.             u_long lastseen;
  598.  
  599.             user = nap_token(&data);
  600.             level = nap_token(&data);
  601.             lastseen = nap_ltoken(&data);
  602.  
  603.             DoMethod(gui->mwin, MSG_WHOWAS, user, level, lastseen);
  604.             }
  605.             break;
  606.         case NAPC_UPLOADREQ:
  607.             {
  608.             char *user, *fname;
  609.             user = nap_token(&data);
  610.             fname = nap_token(&data);
  611.             DoMethod(gui->shwin, SHARE_UPLOAD, user, fname);
  612.             }
  613.             break;
  614.         case NAPC_ALTDLACK:
  615.             {
  616.             char *nick, *fname, *md5;
  617.             u_long ip;
  618.             int port, speed;
  619.  
  620.             nick = nap_token(&data);
  621.             ip = nap_ltoken(&data);
  622.             port = nap_itoken(&data);
  623.             fname = nap_token(&data);
  624.             md5 = nap_token(&data);
  625.             speed = nap_itoken(&data);
  626.  
  627.             ul_startq(fname, nick, NAP_SWAPIP(ip), port, speed);
  628.             }
  629.             break;
  630.         case NAPC_REMOTEQUEUEFULL:
  631.             {
  632.             char *nick, *fname;
  633.             int size, limit;
  634.             nick = nap_token(&data);
  635.             fname = nap_token(&data);
  636.             size = nap_itoken(&data);
  637.             limit = nap_itoken(&data);
  638.  
  639.             DoMethod(gui->dwin, DL_RETRY, fname, nick, limit);
  640.             }
  641.             break;
  642.         case NAPC_GETERROR:
  643.         case NAPC_GETERROR2:
  644.             {
  645.             char *user, *fname;
  646.             user = nap_token(&data);
  647.             fname = nap_token(&data);
  648.             DoMethod(gui->dwin, DL_SETERROR, fname, user, ERROR_LOGGEDOUT);
  649.             }
  650.             break;
  651.         case NAPC_GENERALERROR:
  652.             gui_debugf((char *)MSG_INFO_ERROR, data);
  653.             gRexxCommand = NONE;
  654.             gRC = 10;
  655.             break;
  656.         case NAPC_SYSMSG:
  657.             gui_debug(data);
  658.             break;
  659.         case NAPC_GLOBALMSG:
  660.             {
  661.             char *nick, buf[50];
  662.  
  663.             nick = nap_token(&data);
  664.             sprintf(buf, MSG_GLOBALMESSAGE_TITLE, nick);
  665.  
  666.             MUI_Request(gui->app, gui->win, 0L,
  667.                 buf,
  668.                 (char *)MSG_OK_GAD,
  669.                 data);
  670.             }
  671.             break;
  672.         default:
  673.             gui_debugf("<<%d:%s>>", com, data);
  674.     }
  675. }
  676.  
  677.  
  678. void nap_parseresult(int type, char *data)
  679. {
  680.     song s;
  681.     char *tmp=data;
  682.  
  683.     s = malloc(sizeof(_song));
  684.     if(!s) return;
  685.     memset(s,0,sizeof(_song));
  686.  
  687.     switch (type) {
  688.         case 0:    /* Search result */
  689.             s->title = strdup(nap_token(&tmp));
  690.             s->md5 = strdup(nap_token(&tmp));
  691.             strtok(s->md5,"-");
  692.             s->size = nap_ltoken(&tmp);
  693.             s->bit = nap_itoken(&tmp);
  694.             s->freq = nap_itoken(&tmp);
  695.             s->time = nap_itoken(&tmp);
  696.             s->user = strdup(nap_token(&tmp));
  697.             s->ip = nap_ltoken(&tmp);
  698.             s->ip = NAP_SWAPIP(s->ip);
  699.             s->link = nap_itoken(&tmp);
  700.             break;
  701.  
  702.         case 1: /* Browse result */
  703.             s->user = strdup(nap_token(&tmp));
  704.             s->title = strdup(nap_token(&tmp));
  705.             s->md5 = strdup(nap_token(&tmp));
  706.             strtok(s->md5, "-");
  707.             s->size = nap_ltoken(&tmp);
  708.             s->bit = nap_itoken(&tmp);
  709.             s->freq = nap_itoken(&tmp);
  710.             s->time = nap_itoken(&tmp);
  711.             break;
  712.     }
  713.  
  714.     if (!s->user || !s->title || !s->md5) {
  715.         nap_songfree(s);
  716.         return;
  717.     }
  718.  
  719.     gui_found(s, type);
  720. }
  721.  
  722.  
  723. u_long nap_ltoken(char **str)
  724. {
  725.     char *t;
  726.  
  727.     t = nap_token(str);
  728.     if(!t) return(0);
  729.     return((u_long)atol(t));
  730. }
  731.  
  732.  
  733. int nap_itoken(char **str)
  734. {
  735.     char *t;
  736.  
  737.     t = nap_token(str);
  738.     if(!t) return(0);
  739.     return(atoi(t));
  740. }
  741.  
  742.  
  743. char *nap_token(char **str)
  744. {
  745.     int sf=0,i,len=0;
  746.     char c, *t=NULL;
  747.  
  748.     if (!*str) return(NULL);
  749.  
  750.     for (i=0; ; i++) {
  751.         c = *(*str + i);
  752.         switch (c) {
  753.             case '\0':
  754.                 *str = NULL;
  755.                 if (len==0 || sf) return(NULL);
  756.                 return(t);
  757.             case '"':
  758.                 if (sf) {
  759.                     *(*str+i) = 0;
  760.                     *str = *str+i+1;
  761.                     return(t);
  762.                 }
  763.                 sf=1;
  764.                 break;
  765.             case ' ':
  766.                 if (len==0) break;
  767.                 if (!sf) {
  768.                     *(*str+i) = 0;
  769.                     *str = *str+i+1;
  770.                     return(t);
  771.                 }
  772.                 break;
  773.             default:
  774.                 if (!t) t=*str+i;
  775.                 len++;
  776.         }
  777.     }
  778. }
  779.  
  780.  
  781. #ifdef AMSTER_DEBUG
  782. void ListenerMsgHandler(thread t, int com, APTR data)
  783. {
  784.     listener l=(listener)t->data;
  785.  
  786.     switch (com) {
  787.         case THC_STARTUP:
  788.             l->ts = 1;
  789.             break;
  790.         case THC_EXIT:
  791.             {
  792.             printf("listener thread exit (%d)\n", data);
  793.             l->ts = 0;
  794.             l->t = NULL;
  795.             break;
  796.             }
  797.         case 5:
  798.             DoMethod(gui->dwin, DL_STARTINCOMING, data);
  799.             break;
  800.     }
  801. }
  802.  
  803.  
  804. THREAD(createlistener)
  805. {
  806.     struct sockaddr_in server;
  807.     thread t;
  808.     listener l;
  809.     struct Library *DOSBase;
  810.     struct Library *SocketBase;
  811.     long s;
  812.     thmsg m;
  813.     long alen;
  814.     char buffer[256];
  815.     long tmp;
  816.  
  817.     t = thr_init();
  818.     if (!t) return;
  819.     l = t->data;
  820.  
  821.     l->nsig = AllocSignal(-1);
  822.     if (l->nsig == -1) return;
  823.     l->nsigm = (1L << (l->nsig));
  824.     l->msigm = (1L << (t->port->mp_SigBit));
  825.  
  826.     DOSBase = OpenLibrary("dos.library", 0);
  827.     if (!DOSBase) {
  828.         ExitListenerThread(l, 50);
  829.         return;
  830.     }
  831.     l->DOSBase = DOSBase;
  832.  
  833.     SocketBase = OpenLibrary("bsdsocket.library", 0);
  834.     if (!SocketBase) {
  835.         ExitListenerThread(l, 51);
  836.         return;
  837.     }
  838.     l->SocketBase = SocketBase;
  839.  
  840.     SocketBaseTags(SBTM_SETVAL(SBTC_BREAKMASK), SIGBREAKF_CTRL_F, TAG_DONE);
  841.  
  842.     if (loc_sock != -1) return;
  843.  
  844.     loc_sock = socket(AF_INET, SOCK_STREAM, 0);
  845.     if (loc_sock < 0) {
  846.         printf("Error creating listener socket!\n");
  847.         ExitListenerThread(l, 52);
  848.     }
  849.  
  850.     server.sin_family = AF_INET;
  851.     server.sin_addr.s_addr = htonl(INADDR_ANY);
  852.     server.sin_port = htons(prf->port);
  853.  
  854.     if (bind(loc_sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
  855.         printf("Error binding listening socket (%ld)\n", server.sin_port);
  856.         ExitListenerThread(l, 53);
  857.         return;
  858.     }
  859.  
  860. printf("Listening...\n");
  861.     listen(loc_sock, 5);    /* Number of allowed connections */
  862.  
  863.     alen = sizeof(server);
  864.  
  865.     while (1) {
  866.         l->s = accept(loc_sock, (struct sockaddr *)&server, &alen);
  867. printf("Connection accepted!\n");
  868.  
  869.         if (l->s == -1) break;
  870.  
  871.         send(l->s, "1", 1, 0);
  872.         tmp = recv(l->s, buffer, 255, 0);
  873.         if (tmp < 1) {
  874.             CloseSocket(l->s);
  875.             l->s = NULL;
  876.         }
  877.         else {
  878.             buffer[tmp] = '\0';
  879.  
  880. printf("IN-REQ (sock: %ld): %s\n", l->s, buffer);
  881.  
  882.             if (strcmp(buffer, "SEND") == 0) {
  883.                 thr_message(t, 5, (APTR)ReleaseSocket(l->s, GetUniqueID()));
  884.             }
  885.         }
  886.     }
  887.  
  888.     ExitListenerThread(l, 0);
  889.     return;
  890. }
  891.  
  892.  
  893. void ExitListenerThread(listener l, int ret)
  894. { /* Inside the thread */
  895.     struct Library *DOSBase = l->DOSBase;
  896.     struct Library *SocketBase = l->SocketBase;
  897.  
  898. /*
  899.     if (loc_sock != -1) {
  900.         CloseSocket(loc_sock);
  901.         loc_sock = -1;
  902.     }
  903. */
  904.  
  905.     if (l->nsig != -1) {
  906.         FreeSignal(l->nsig);
  907.         l->nsig = -1;
  908.     }
  909.  
  910.     if (SocketBase) {
  911.         CloseLibrary(SocketBase);
  912.         l->SocketBase = NULL;
  913.     }
  914.  
  915.     if (DOSBase) {
  916.         CloseLibrary(DOSBase);
  917.         l->DOSBase = NULL;
  918.     }
  919.  
  920.     thr_exit(l->t, ret);
  921. }
  922. #endif
  923.  
  924.  
  925. char *getneterror(int type)
  926. {
  927.     char *message, buf[512];
  928.  
  929.     switch (type) {
  930.         case ENETDOWN:
  931.             message = (char *)MSG_NETERROR_ENETDOWN;
  932.             break;
  933.         case ENETUNREACH:
  934.             message = (char *)MSG_NETERROR_ENETUNREACH;
  935.             break;
  936.         case ECONNRESET:
  937.             message = (char *)MSG_NETERROR_ECONNRESET;
  938.             break;
  939.         case ETIMEDOUT:
  940.             message = (char *)MSG_NETERROR_ETIMEDOUT;
  941.             break;
  942.         case ECONNREFUSED:
  943.             message = (char *)MSG_NETERROR_ECONNREFUSED;
  944.             break;
  945.         case EPIPE:
  946.             message = (char *)MSG_NETERROR_EPIPE;
  947.             break;
  948.         default:
  949.             sprintf(buf, MSG_NETERROR_UNKNOWN, type);
  950.             message = buf;
  951.     }
  952.  
  953.     return message;
  954. }
  955.